﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using DirkRettschlag.Utils;

namespace Departure
{
    public partial class ctrlLabel : UserControl
    {
        #region Delegates

        #endregion Delegates

        #region Variables

        StringFormat m_stringFormat;

        SkinSettings skinSettings;

        bool vga = false;

        // Background drawing
        Bitmap backBufferBitmap;
        Graphics backBuffer;

        Image imageBG = new Bitmap(240, 16);
        Rectangle rectangleImageBG;
        SizeF sizeFont;
        SolidBrush drawStringBrush;
        
        string text;
        TextHAlignment textHorizontalAlignment = TextHAlignment.Left;

        #endregion Variables

        #region Enums
        
        public enum TextHAlignment
        {
            Left,
            Right,
            Center
        }

        #endregion Enums
        
        #region Constructor

        public ctrlLabel()
        {
            InitializeComponent();

            CreateBackBuffer();

            m_stringFormat = new StringFormat();
            m_stringFormat.Alignment = StringAlignment.Near;
            m_stringFormat.FormatFlags = StringFormatFlags.NoWrap;
            drawStringBrush = new SolidBrush(ForeColor);
        }

        public ctrlLabel(string text, bool vga, Image Background)
        {
            this.text = text;
            this.vga = vga;
            this.imageBG = Background;

            InitializeComponent();

            CreateBackBuffer();

            m_stringFormat = new StringFormat();
            m_stringFormat.Alignment = StringAlignment.Near;
            m_stringFormat.FormatFlags = StringFormatFlags.NoWrap;
            drawStringBrush = new SolidBrush(ForeColor);
        }

        #endregion Constructor

        #region Overidden Methods
        /// <summary>
        /// Paints the background of the control.
        /// </summary>
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            // Do nothing
        }

        /// <summary>
        /// Paints the control.
        /// </summary>
        protected override void OnPaint(PaintEventArgs e)
        {
            if (backBuffer != null)
            {
#if DEBUG
                Stopwatch stopWatch = Stopwatch.StartNew();
#endif
                if (vga)
                {
                    backBuffer.DrawImage(imageBG, this.ClientRectangle, rectangleImageBG, GraphicsUnit.Pixel);

                    using (Font f2 = Utilities.AppropriateFont(backBuffer, 5, 14, new Size(this.ClientRectangle.Width - 4, this.ClientRectangle.Height), this.Text, this.Font, out sizeFont))
                    {
                        switch (textHorizontalAlignment)
                        {
                            case TextHAlignment.Left:
                                backBuffer.DrawString(text, f2, drawStringBrush, 2, ((this.ClientRectangle.Height - sizeFont.Height) / 2));
                                break;
                            case TextHAlignment.Center:
                                backBuffer.DrawString(text, f2, drawStringBrush, ((this.ClientRectangle.Width - sizeFont.Width) / 2), ((this.ClientRectangle.Height - sizeFont.Height) / 2));
                                break;
                            case TextHAlignment.Right:
                                backBuffer.DrawString(text, f2, drawStringBrush, this.ClientRectangle.Width - sizeFont.Width - 2, ((this.ClientRectangle.Height - sizeFont.Height) / 2));
                                break;
                        }
                    }

                    e.Graphics.DrawImage(backBufferBitmap, 0, 0);
                }
                else
                {
                    backBuffer.DrawImage(imageBG, this.ClientRectangle, rectangleImageBG, GraphicsUnit.Pixel);

                    using (Font f2 = Utilities.AppropriateFont(backBuffer, 5, 14, new Size(this.ClientRectangle.Width - 2, this.ClientRectangle.Height), this.Text, this.Font, out sizeFont))
                    {
                        switch (textHorizontalAlignment)
                        {
                            case TextHAlignment.Left:
                                backBuffer.DrawString(text, f2, drawStringBrush, 1, ((this.ClientRectangle.Height - sizeFont.Height) / 2));
                                break;
                            case TextHAlignment.Center:
                                backBuffer.DrawString(text, f2, drawStringBrush, ((this.ClientRectangle.Width - sizeFont.Width) / 2), ((this.ClientRectangle.Height - sizeFont.Height) / 2));
                                break;
                            case TextHAlignment.Right:
                                backBuffer.DrawString(text, f2, drawStringBrush, this.ClientRectangle.Width - sizeFont.Width, ((this.ClientRectangle.Height - sizeFont.Height) / 2));
                                break;
                        }
                    }

                    e.Graphics.DrawImage(backBufferBitmap, 0, 0);
                }
#if DEBUG
                stopWatch.Stop();

                Debug.WriteLine("Label Render Time:   " + stopWatch.ElapsedMilliseconds.ToString());
#endif
            }
            else
            {
                base.OnPaint(e);
            }
        }

        /// <summary>
        /// Called when the control is resized.
        /// </summary>
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            rectangleImageBG = new Rectangle(0, 0, imageBG.Width, imageBG.Height);
            CreateBackBuffer();
            Invalidate();
        }

        #endregion Overridden Methods

        #region Properties

        public SkinSettings SkinSettings
        {
            get
            {
                return skinSettings;
            }
            set
            {
                skinSettings = value;
                if (skinSettings != null)
                {
                    this.ForeColor = skinSettings.FontColor;
                    this.drawStringBrush = new SolidBrush(this.skinSettings.FontColor);
                }
                Invalidate();
            }
        }

        public bool VGA
        {
            get { return this.vga; }
            set { this.vga = value; }
        }

        public Image ImageBG
        {
            get
            {
                return this.imageBG;
            }
            set
            {
                this.imageBG = value;
                rectangleImageBG = new Rectangle(0, 0, imageBG.Width, imageBG.Height);
                Invalidate();
            }
        }

        public override string Text
        {
            get
            {
                return this.text;
            }
            set
            {
                this.text = value;
                if (this.text == "")
                    this.Visible = false;
                else
                    this.Visible = true;

                Invalidate();
            }
        }

        public TextHAlignment TextHorizontalAlignment
        {
            get
            {
                return this.textHorizontalAlignment;
            }
            set
            {
                this.textHorizontalAlignment = value;
            }
        }
        
        #endregion Properties

        /// <summary>
        /// Cleans up the background paint buffer.
        /// </summary>
        private void CleanupBackBuffer()
        {
            if (backBufferBitmap != null)
            {
                backBufferBitmap.Dispose();
                backBufferBitmap = null;
                backBuffer.Dispose();
                backBuffer = null;
            }
        }

        /// <summary>
        /// Creates the background paint buffer.
        /// </summary>
        private void CreateBackBuffer()
        {
            CleanupBackBuffer();

            backBufferBitmap = new Bitmap(Bounds.Width, Bounds.Height);
            backBuffer = Graphics.FromImage(backBufferBitmap);
        }
    }
}
